package com.remoter.basic.provider.support;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.remoter.basic.bean.support.ProviderModule;
import com.remoter.basic.bean.support.RemoterRequest;
import com.remoter.basic.provider.IProvider;
import com.remoter.basic.transport.IServer;
import com.remoter.basic.util.ServiceLoader;

/**
 * @author			koko
 * @date 			2017-08-10 13:49:40
 * @description 	类功能说明
 */
public abstract class AbstractProvider implements IProvider{
	
	protected static final Logger logger = LoggerFactory.getLogger(AbstractProvider.class);
	
	protected ConcurrentHashMap<String,IServer> servers = new ConcurrentHashMap<String,IServer>();
	
	@Override
	public void close() throws IOException {
		for(Entry<String,IServer> entry : this.servers.entrySet()){
			try{
				entry.getValue().unBind();
			}catch(Exception e){
				logger.error(e.getMessage(),e);
			}
		}
		this.servers.clear();
	}

	@Override
	public void bind(ProviderModule providerModule)throws Exception{
		String key = this.createKey(providerModule);
		if(this.servers.containsKey(key)){
			this.servers.get(key).attachProvider(providerModule);
		}else{
			IServer server = ServiceLoader.getService(IServer.class,providerModule.getProtocol());
			if(null == server){
				throw new IllegalStateException("protocol not found");
			}
			server.bind(new InetSocketAddress(providerModule.getHost(),providerModule.getPort()));
			server.attachProvider(providerModule);
			servers.put(key,server);
		}
	}

	@Override
	public void unBind(ProviderModule providerModule)throws Exception{
		String key = this.createKey(providerModule);
		if(this.servers.containsKey(key)){
			this.servers.get(key).unBind();
			this.servers.remove(key);
		}
	}
	
	@Override
	public IServer getServer(ProviderModule providerModule, boolean autoBind) throws Exception {
		String key = this.createKey(providerModule);
		IServer server = this.servers.get(key);
		if(null == server && autoBind){
			this.bind(providerModule);
			server = this.servers.get(key);
		}else{
			server.attachProvider(providerModule);
		}
		return this.servers.get(key);
	}
	
	@Override
	public ProviderModule getProviderModule(RemoterRequest remoterRequest){
		String key = this.createKey(remoterRequest);
		if(this.servers.containsKey(key)){
			return this.servers.get(key).getProviderModule(remoterRequest);
		}
		return null;
	}
	
	private String createKey(ProviderModule providerModule){
		return String.format("%s-%s-%s",providerModule.getProtocol(),providerModule.getHost(),providerModule.getPort());
	}
	
	private String createKey(RemoterRequest remoterRequest){
		return String.format("%s-%s-%s",remoterRequest.getProtocol(),remoterRequest.getToHost(),remoterRequest.getToPort());
	}
	
}